package com.cwz.datasource.dynamic.interceptor;

import com.alibaba.druid.pool.DruidDataSource;
import com.cwz.core.constant.HttpStatus;
import com.cwz.core.constant.SecurityConstants;
import com.cwz.core.context.DataSourceContextHolder;
import com.cwz.core.utils.servle.ServletUtils;
import com.cwz.core.utils.spring.SpringUtils;
import com.cwz.core.utils.string.StringUtils;
import com.cwz.datasource.dynamic.config.DynamicRoutingDataSource;
import com.cwz.datasource.dynamic.utils.DataSourceUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @program: w-demo
 * @description: 动态数据库拦截器
 * @author: Wen
 **/
public class DataSourceInterceptor implements HandlerInterceptor {
	// preHandler
	// 调用时间：Controller方法处理之前
	// 执行顺序：链式Intercepter情况下，Intercepter按照声明的顺序一个接一个执行
	// 注意事项：若返回false，则中断执行，不会进入afterCompletion
	// postHandler
	// 调用前提：preHandle返回true
	// 调用时间：Controller方法处理完之后，DispatcherServlet进行视图的渲染之前，也就是说在这个方法中你可以对ModelAndView进行操作
	// 执行顺序：链式Intercepter情况下，Intercepter按照声明的顺序倒着执行
	// afterCompletion
	// 调用前提：preHandle返回true
	// 调用时间：DispatcherServlet进行视图的渲染之后
	// 注意事项：多用于清理资源

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String company = request.getHeader(SecurityConstants.DETAILS_COMPANY);
		DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean("dynamicRoutingDataSource");
		DruidDataSource baseDatasource = (DruidDataSource) dynamicRoutingDataSource.getTargetDataSources().get("baseDatasource");
		Connection conn = null;
		try {
			conn = baseDatasource.getConnection();
			// 判断公司存不存在
			if (!checkCompany(conn, company)) {
				ServletUtils.outResponse(response, "当前用户所属公司不存在，访问失败，请联系管理员", HttpStatus.ERROR);
				return false;
			}
			DataSourceContextHolder.set(company);
		}  catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		DataSourceContextHolder.remove();
	}

	private boolean checkCompany(Connection conn, String company) {
		// 1.准备返回容器
		PreparedStatement ps = null;
		ResultSet rs = null;
		boolean result = false;
		try {
			// 2.编写sql语句
			// 3.获取sql预编译对象
			// TODO: 2023/7/5 这里要把以后的具体某个 sql 语句给写上
			ps = conn.prepareStatement("select id from sys_company where is_delete = 0 and company = ?");
			// 4.设置参数给占位符
			ps.setString(1, company);
			// 5.执行并保存结果集
			rs = ps.executeQuery();
			// 6.处理结果集
			if (rs.next() && StringUtils.isNotNull(rs.getObject("id", Long.class))) {
				result = true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 释放连接资源
			DataSourceUtils.release(conn, ps, rs);
		}
		return result;
	}

}
